import asyncio
from datetime import datetime

from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.job import Job
from fastapi import FastAPI

from afast_core.core_plugins.loguru import logger
from afast_core.core_plugins.pluginbase import IBasePlugin as BasePlugin
from pydantic import BaseSettings as Settings
from typing import Union

class Scheduler:
    """
    AsyncIOScheduler 封装
    """
    scheduler: AsyncIOScheduler



    def shutdown(self):
        self.scheduler.shutdown()


    def init_scheduler(self,setting):
        self.scheduler = AsyncIOScheduler(timezone='Asia/Shanghai')
        # {"default": SQLAlchemyJobStore(url=setting.url)}
        self.job_dict: Union[dict] = {} or setting.job_dict
        self.scheduler.start()
        logger.info('服务已开启', event_name='定时任务模块')

        # 测试
        def tick():
            print('测试任务-Tick! The time is: %s' % datetime.now())

        self.scheduler.add_job(tick, 'interval', seconds=3)
        # 同步数据库任务
        # Scheduler.add(Task.refresh_database_task, job_name='同步数据库',
        #               trigger='cron', minute="0", second='0')


    def add(self, func: callable, job_name: str, **kwargs):
        """
        添加任务，并保存到 job_dict
        :param func: 任务执行函数
        :param job_name: 任务名称，对应job_dict的key
        :param kwargs: 其他传入add_job的参数
        """
        if job_name in self.job_dict:
            raise Exception(f"the job with name '{job_name}' already exists")

        #   附加job_name参数
        if 'kwargs' not in kwargs:
            kwargs['kwargs'] = {'job_name': job_name}
        elif 'job_name' not in kwargs['kwargs']:
            kwargs['kwargs']['job_name'] = job_name

        self.job_dict[job_name] = self.scheduler.add_job(func=func, **kwargs)
        logger.info(f'定时任务[{job_name}]已添加, 当前任务数量:{len(self.job_dict)}', event_name='定时任务模块')

    @classmethod
    def remove(cls, job_name: str):
        """
        移除任务，同时删除 job_dict 中键值对
        """
        if job_name not in cls.job_dict:
            raise Exception(f"the job with name '{job_name}' doesn't exist")
        job: Job = cls.job_dict[job_name]
        job.remove()
        del cls.job_dict[job_name]
        logger.info(f'定时任务[{job_name}]已移除, 当前任务数量:{len(cls.job_dict)}', event_name='定时任务模块')


class ApschedulerPluginClient(Scheduler, BasePlugin):
    # 设置插件默认的参数信息
    name = 'RocketryScheduler插件'

    class SchedulerConfig(Settings):
        job_dict: dict = None

    def setup(self, app: FastAPI, name: str = None, *args, **kwargs):
        """插件初始化"""

        @app.on_event("startup")
        async def start_scheduler() -> None:
            self.init_scheduler(setting=self.settings)
            logger.info(f"startup event - {self.scheduler.state=}", event_name='定时任务模块')

        @app.on_event("shutdown")
        async def stop_scheduler() -> None:
            self.shutdown()
            await asyncio.sleep(5)
            logger.info(f"shutdown event - {self.scheduler.state=}", event_name='定时任务模块')

# class Task:
#     @staticmethod
#     def clear_phone_verification_task(job_name: str):
#         """
#         定时任务，清理过期验证码，重置剩余验证码次数
#         """
#         try:
#             sql1 = 'DELETE FROM phone_verification WHERE NOW() > expiration;'
#             sql2 = 'UPDATE phone_verification SET sendTimes = 0 WHERE sendTimes!=0;'
#             with Mysql.connect() as conn:
#                 Mysql.execute_only(conn, sql1)
#                 Mysql.execute_only(conn, sql2)
#                 conn.commit()
#             logger.success(f'定时任务[{job_name}]已完成')
#         except Exception as e:
#             logger.error(f'定时任务[{job_name}]发生错误:{e}')
#
#     @staticmethod
#     def refresh_database_task(job_name: str):
#         """
#         定时任务 通过获取微信数据库同步本地mysql数据库
#         """
#         try:
#             UpdateDataBase.update_canteen_table()
#             logger.success(f'定时任务[{job_name}]已完成')
#         except Exception as e:
#             logger.error(f'定时任务[{job_name}]发生错误:{e}')
